/**
 * @author: Christopher Rabotin
 * communication.h gère toutes les communications au sein du programme.
 * Grâce aux defines, ce header exécute les bonnes méthodes.
 * Les communications disponibles sont:
 * 		+ par fichiers: implémentation bouchon
 * 		+ par pipe (ou tube): implémentation demandée
 * 		+ par socket: implémentation supplémentaire
 */

#ifndef COMMUNICATION_H_
#define COMMUNICATION_H_ 
#include "../src/casual_includes.h"
#include <unistd.h>
#include <sys/types.h> 
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h> 
#include <sys/wait.h>
#include <netdb.h> 

#include "message.h"

#define MAXRECVDATA 1024 /* nombre de serveurs à être initialisés */
/**
 * TYPE permet de différencier les types de modules
 * ack: type acquisition
 * exec: type exécution
 * term: type terminal (important car très différent des autres)
 * interb: type interboursier
 */
enum TYPE {ack,exec,term,interb};

/**
 * server comprend toutes les données nécessaires au bon fonctionnement d'un serveur.
 * Attention, ici le terme "serveur" est un abus de langage puisque même un terminal est considéré
 * comme un serveur alors que, comme en témoigne le code de init_server(), terminal est bel et bien
 * un client (établie une connexion au lieu d'attendre une connexion).
 */
typedef struct server_struct {
	int isAlive; /* permet de savoir si le serveur tourne ou non */
	char name[128]; /* nom du serveur (Acquisition, Execution, Terminal) */
	int sockfd; /* descripteur du socket */
	int my_port; /* port du serveur*/
	int max_conn; /* nombre maximal de connexions */
	int numbytes; /* nombre d'octets reçus par une connexion */
	socklen_t sin_size; /* taille du socket */
	struct sockaddr_in local_addr; /* adresse locale */
	struct sockaddr_in remote_addr; /* adresse distante*/
	msg *recvdata; /* données reçues */
} server;

/**
 * module comprend quelques informations permet d'identifier les modules entre-eux
 */
typedef struct module_struct {
	server *srv; /* permet de stocker dans le module le serveur associé */
	int type; /* distingue les modules par leur type (voir l'enum TYPE) */
	char name[128]; /* nom du module */
	int bourse_id; /* bourse dans lequel le module est intégré */
} module;

/**
 * Permet d'initialiser un module
 * @param nom le nom du module
 * @param type le type du module: voir l'enum TYPE
 * @param bourse la bourse dans laquelle est placé le module
 */
module* init_module(char *nom, int type, int bourse);
/**
 * Permet d'initialiser un "vrai" serveur (voir documentation du struct server).
 * @param mdl module associé au serveur
 * @param port port d'écoute des connexions
 * @param max_connexions connexions maximum que el serveur est censé gérer
 */
void init_server(module* mdl, const int port, const int max_connexions);

/**
 * Permet d'initialiser un client, i.e. un "faux" serveur (voir documentation du struct server).
 * @param mdl module associé au client
 * @param acks tableau des modules d'acquisition
 */
void init_client(module* mdl, module* acks);
/**
 * Envoi d'un message par socket vers le bon serveur. Il suffit de passer en paramètre
 * le bon client (toAck,toExec,toTerm) et le message (msg) à envoyer.
 * @param mdl module qui envoie le message
 * @param srv_dest le serveur destinataire du message
 * @param damsg le message à envoyer
 */
void send_msg(const module* mdl, const server* srv_dest, msg* damsg);

/**
 * Permet de logguer les communications des serveurs. Placé dans communication.h puisque
 * utilisé uniquement pour la communication par socket.
 * @param srv le serveur d'où le log émane
 * @param un_msg message d'explication lié à l'ordre de transaction 
 */
void log_srv(const server* srv, char* un_msg);


#endif /*COMMUNICATION_H_*/
